package com.geoai.featstatusbar.mvi.vm

import android.util.Log
import androidx.lifecycle.MutableLiveData
import com.geoai.basiclib.base.mvi.BaseEISViewModel
import com.geoai.featstatusbar.mvi.eis.TopStatusBarEffect
import com.geoai.featstatusbar.mvi.eis.TopStatusBarIntent
import com.geoai.featstatusbar.mvi.eis.TopStatusBarState
import com.geoai.mavlink.geoainet.airlink.info.CellularServerConnectionInfo
import com.geoai.mavlink.geoainet.flycontroller.info.AircraftDiagnosticsStateInfo
import com.geoai.mavlink.geoainet.rtk.enums.GPSPosType
import com.zkyt.lib_msdk_ext.ProductManagerExt
import com.zkyt.lib_msdk_ext.component.AirLinkManagerExt
import com.zkyt.lib_msdk_ext.component.BatteryManagerExt
import com.zkyt.lib_msdk_ext.component.FlyControllerManagerExt
import com.zkyt.lib_msdk_ext.component.RtkManagerExt
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.rxkotlin.addTo
import java.util.concurrent.TimeUnit
import javax.inject.Inject

/**
 * @Author      : Ronny
 * @Email       : Ronny_xie@hotmail.com
 * @Date        : on 2024-04-03 19:33.
 * @Description :
 */
class TopStatusBarViewModel @Inject constructor(): BaseEISViewModel<TopStatusBarEffect, TopStatusBarIntent, TopStatusBarState>(){

    val isHmsFlexViewVisibility : MutableLiveData<Boolean> = MutableLiveData(false)

    override fun initUiState(): TopStatusBarState = TopStatusBarState.DroneConnected(false)

    init {
        registerProductConnectedStatus { sendUiState(TopStatusBarState.DroneConnected(it)) }

        registerFlightModeStatus { sendUiState(TopStatusBarState.DroneFlyMode(it)) }

        registerWirelessStatus { sendUiState(TopStatusBarState.DroneWirelessSignal(it.first, it.second)) }

        registerDroneSatelliteStatus { sendUiState(TopStatusBarState.DroneSatelliteCount(it.first.toInt(), it.second)) }

        registerDroneBatteryStatus { sendUiState(TopStatusBarState.DroneBatteryPercent(it)) }

        registerDroneCellularStatus({ sendUiState(TopStatusBarState.DroneCellularStatus(it)) }, { sendUiState(TopStatusBarState.DroneCellularStatus(null)) })

        registerDroneHmsStatus { sendUiState(TopStatusBarState.DroneHmsStatus(it)) }
    }

    override fun handleIntent(intent: TopStatusBarIntent) {
        when(intent) {
            is TopStatusBarIntent.ProductConnected -> {
                launchOnUI { sendUiState(TopStatusBarState.DroneConnected(intent.isConnected)) }
            }
        }
    }

    private fun registerProductConnectedStatus(successBlock: (e: Boolean) -> Unit) {
        ProductManagerExt.getConnectedObservable()
            .distinctUntilChanged()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                successBlock.invoke(it)
            }.addTo(compositeDisposable)
    }

    private fun registerFlightModeStatus(successBlock: (e: String) -> Unit) {
        FlyControllerManagerExt.getFlyControllerStateObservable()
            .filter { it.isPresent }
            .throttleLast(1, TimeUnit.SECONDS)
            .map { it.get().flyMode.name }
            .subscribe {
                successBlock.invoke(it)
            }.addTo(compositeDisposable)
    }

    private fun registerWirelessStatus(successBlock: (Pair<Int, Int>) -> Unit) {
        AirLinkManagerExt.getWirelessSignalInfoObservable()
            .filter{ it.isPresent }
            .map { Pair((6 - it.get().uplinkSignalLevel.value()) * 20, (6 - it.get().downlinkSignalLevel.value()) * 20) }
            .subscribe {
                successBlock.invoke(it)
            }.addTo(compositeDisposable)
    }

    private fun registerDroneSatelliteStatus(successBlock: (Pair<Short, String>) -> Unit) {
        RtkManagerExt.getRtkStateInfoObservable()
            .filter { it.isPresent }
            .map {
                val rt = when (it.get().posType) {
                    GPSPosType.GPS_FIX_TYPE_DGPS -> "Gps"
                    GPSPosType.GPS_FIX_TYPE_RTK_FLOAT -> "Float"
                    GPSPosType.GPS_FIX_TYPE_RTK_FIXED -> "Fixed"
                    else -> "N"
                }
                Pair(it.get().satelliteCount, rt)
            }
            .subscribe {
                successBlock.invoke(it)
            }.addTo(compositeDisposable)
    }

    private fun registerDroneBatteryStatus(successBlock: (e: Int) -> Unit) {
        BatteryManagerExt.getBatteryStateInfoObservable()
            .filter{ it.isPresent}
            .subscribe {
                successBlock.invoke(it.get()[0].batteryRemainingPercentage)
            }.addTo(compositeDisposable)
    }

    private fun registerDroneCellularStatus(successBlock: (e: CellularServerConnectionInfo) -> Unit, errorBlock: () -> Unit) {
        Observable.interval(0, 1000, java.util.concurrent.TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                AirLinkManagerExt.getCellularStatusRx().subscribe({
                    successBlock.invoke(it)
                }, {
                    errorBlock.invoke()
                }).addTo(compositeDisposable)
            }.addTo(compositeDisposable)
    }

    private fun registerDroneHmsStatus(successBlock: (info: List<AircraftDiagnosticsStateInfo>) -> Unit) {
        FlyControllerManagerExt.getDiagnosticsStateObservable()
            .throttleLast(3, TimeUnit.SECONDS)
            .filter { it.isPresent }
            .map { it.get() }
            .filter {it.isNotEmpty()}
            .subscribe {
                successBlock.invoke(it)
            }.addTo(compositeDisposable)
    }
}